package com.taijihuabao.modules.service.impl;

import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.taijihuabao.common.constant.ConstantUtils;
import com.taijihuabao.common.exception.ServiceException;
import com.taijihuabao.common.jsonresult.ApplicationResponseCode;
import com.taijihuabao.common.redisconfig.UserLoad;
import com.taijihuabao.modules.entity.*;
import com.taijihuabao.modules.mapper.*;
import com.taijihuabao.modules.service.ExpenseFlowService;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;


/**
 * @author luoxianan
 */
@Service
@Slf4j
public class ExpenseFlowServiceImpl implements ExpenseFlowService {
    private  final String ACTIVITI_KEY = "EXPENSE";

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private ExpenseMapper expenseMapper;
    @Autowired
    private DeptUserMapper deptUserMapper;
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private ChaimMapper chaimMapper;
    @Override
    public void saveNewDeploye() {
        repositoryService.createDeployment()
                .addClasspathResource("bpmn/expense.bpmn")
                .name("报销审批流程")
                .deploy();
    }
    HashMap<String, Object> map = new HashMap<>(7);
    @Override
    public void initApply(ExpenseEntity expenseEntity) {
        ExpenseEntity expenseEntity2 = expenseMapper.selectByExpenseId(expenseEntity);
        if (expenseEntity2 !=null){
            // 驳回重新申请
            if(ConstantUtils.APPLY.equals(expenseEntity2.getExpenseType())){
                taskService.complete(expenseEntity2.getExpenseTask());
                String s = String.valueOf(expenseEntity2.getId());
                Task task1 = updateExpense(s);
                expenseEntity.setExpenseTask(task1.getId());
                expenseEntity.setExpenseType(ConstantUtils.DEPT_APPROVAL);
                expenseMapper.updateExpense(expenseEntity);
            } else {
                throw new ServiceException(ApplicationResponseCode.NO_DUPLICATE_SUBMIT);
            }
        }else {
            // 启动流程实例
            expenseEntity.setExpenseState(ConstantUtils.PASS);
            expenseMapper.insertExpense(expenseEntity);
            ExpenseEntity expenseEntity1 = expenseMapper.selectByExpenseId(expenseEntity);
            String s = String.valueOf(expenseEntity1.getId());
            runtimeService.startProcessInstanceByKey(ACTIVITI_KEY,s);
            Long id = UserLoad.getUser().getId();
            List<DeptUserEntity> deptUserEntities = deptUserMapper.selectDeptByUserId(id);
            Task task = taskService.createTaskQuery()
                    .taskId(updateExpense(s).getId())
                    .taskAssignee(String.valueOf(id))
                    .singleResult();
            expenseEntity.setApplyUserId(id);
            expenseMapper.updateExpense(expenseEntity);
            taskService.complete(task.getId());
            //插入任务号
            Task task1 = updateExpense(s);
            expenseEntity.setExpenseTask(task1.getId());
            expenseEntity.setExpenseType(ConstantUtils.DEPT_APPROVAL);
            expenseEntity.setApplyDeptCode(deptUserEntities.get(0).getDeptCode());
            expenseMapper.updateExpense(expenseEntity);
        }

    }

    @Override
    public void deptExpense(ExpenseEntity expenseEntity) {
        double money = 5000;
        //判断登录人员是否有父级部门
        List<DeptUserEntity> deptUserEntities = deptUserMapper.selectDeptByUserId(expenseEntity.getApplyUserId());
        if (ConstantUtils.PASS.equals(expenseEntity.getExpenseState())) {
            DeptEntity deptEntity = deptMapper.selectDeptByCode(deptUserEntities.get(0).getDeptCode());
            String parentDept = deptEntity.getParentDept();
            //判断金额是否大于5000，直接关联报销表查询即可
            ExpenseEntity expenseEntity1 = expenseMapper.selectByExpenseId(expenseEntity);
            if(expenseEntity1.getApplyMoney()<=money){
                //如果金额小于5000，直接走财务审批
                map.put(ConstantUtils.DEPT_NODE,ConstantUtils.FINANCE);
                expenseEntity.setExpenseType(ConstantUtils.FINANCE_APPROVAL);
            } else {
                if (parentDept.isEmpty()) {
                    //没有父级部门，直接进财务部审批
                    //报销的时候查询金额,判断金额
                    map.put(ConstantUtils.DEPT_NODE,ConstantUtils.FINANCE);
                    expenseEntity.setExpenseType(ConstantUtils.FINANCE_APPROVAL);
                } else {
                    //有父级部门，进入父级部门审批
                    map.put(ConstantUtils.DEPT_NODE, ConstantUtils.PASS);
                    expenseEntity.setExpenseType(ConstantUtils.PARENT_APPROVAL);
                }
            }
        }
        ChaimEntity chaimEntity = new ChaimEntity();
        if (ConstantUtils.REFUSE.equals(expenseEntity.getExpenseState())){
            map.put(ConstantUtils.DEPT_NODE,ConstantUtils.REFUSE);
            expenseEntity.setExpenseType(ConstantUtils.END);
            expenseEntity.setDeleteMark(ConstantUtils.DELETE_MARK);
            chaimEntity.setChaimStatus(Integer.valueOf(ConstantUtils.REFUSE));
            chaimEntity.setChaimCode(expenseEntity.getExpenseId());
            chaimMapper.updateChaimStatus(chaimEntity);
            expenseEntity.setExpenseState(ConstantUtils.REFUSE);
        }
        if (ConstantUtils.REJECT.equals(expenseEntity.getExpenseState())){
            map.put(ConstantUtils.DEPT_NODE,ConstantUtils.REJECT);
            expenseEntity.setExpenseType(ConstantUtils.APPLY);
            chaimEntity.setChaimStatus(Integer.valueOf(ConstantUtils.REJECT));
            chaimEntity.setChaimCode(expenseEntity.getExpenseId());
            chaimMapper.updateChaimStatus(chaimEntity);
            expenseEntity.setExpenseState(ConstantUtils.REJECT);
        }
        taskService.complete(expenseEntity.getExpenseTask(),map);
        //插入任务号
        ExpenseEntity expenseEntity1 = expenseMapper.selectByExpenseId(expenseEntity);
        String s = String.valueOf(expenseEntity1.getId());
        Task task1 = updateExpense(s);
        if (!ConstantUtils.REFUSE.equals(expenseEntity.getExpenseState())) {
            expenseEntity.setExpenseTask(task1.getId());
        }
        if (ConstantUtils.REJECT.equals(expenseEntity.getExpenseState())){
            map.clear();
        }
        expenseMapper.updateExpense(expenseEntity);

    }

    @Override
    public void parentExpense( Long userId,ExpenseEntity expenseEntity) {
        ExpenseEntity expenseEntity1 = expenseMapper.selectByExpenseId(expenseEntity);
        String s = String.valueOf(expenseEntity1.getId());
        String deptRole =  deptUserMapper.selectDeptByUserId(expenseEntity1.getExpenseUserId()).get(0).getDeptRole();
        //审核员
        if (ConstantUtils.ADMINISTRATOR.equals(deptRole) || ConstantUtils.ASSESSOR.equals(deptRole)) {
            parentExpenseMap(expenseEntity, map);
            taskService.claim(expenseEntity.getExpenseTask(), String.valueOf(userId));
            taskService.complete(expenseEntity.getExpenseTask(), map);
            //插入任务号
            Task task1 = updateExpense(s);
            if (!ConstantUtils.REFUSE.equals(expenseEntity.getExpenseState())) {
                expenseEntity.setExpenseTask(task1.getId());
            }
            expenseMapper.updateExpense(expenseEntity);
        }
        if (ConstantUtils.REJECT.equals(expenseEntity.getExpenseState())){
            map.clear();
        }
    }

    /**
     * 父级审批给流程变量赋值
     * @param expenseEntity  审批实体
     * @param map 流程变量容器
     */
    private void parentExpenseMap(ExpenseEntity expenseEntity, HashMap<String, Object> map) {
        ChaimEntity chaimEntity = new ChaimEntity();
        if (equalsPass(expenseEntity)) {
            map.put(ConstantUtils.PARENT_DEPT_NODE, ConstantUtils.PASS);
            expenseEntity.setExpenseType(ConstantUtils.FINANCE_APPROVAL);
        }
        if (equalsRefuse(expenseEntity)) {
            map.put(ConstantUtils.PARENT_DEPT_NODE, ConstantUtils.REFUSE);
            expenseEntity.setExpenseType(ConstantUtils.END);
            expenseEntity.setDeleteMark(ConstantUtils.DELETE_MARK);
            chaimEntity.setChaimStatus(Integer.valueOf(ConstantUtils.REFUSE));
            chaimEntity.setChaimCode(expenseEntity.getExpenseId());
            chaimMapper.updateChaimStatus(chaimEntity);
            expenseEntity.setExpenseState(ConstantUtils.REFUSE);
        }
        if (equalsReject(expenseEntity)) {
            map.put(ConstantUtils.PARENT_DEPT_NODE, ConstantUtils.REJECT);
            expenseEntity.setExpenseType(ConstantUtils.APPLY);
            chaimEntity.setChaimStatus(Integer.valueOf(ConstantUtils.REJECT));
            chaimEntity.setChaimCode(expenseEntity.getExpenseId());
            chaimMapper.updateChaimStatus(chaimEntity);
            expenseEntity.setExpenseState(ConstantUtils.REJECT);
        }
    }

    private boolean equalsReject(ExpenseEntity expenseEntity) {
        return ConstantUtils.REJECT.equals(expenseEntity.getExpenseState());
    }

    private boolean equalsPass(ExpenseEntity expenseEntity) {
        return ConstantUtils.PASS.equals(expenseEntity.getExpenseState());
    }

    private boolean equalsRefuse(ExpenseEntity expenseEntity) {
        return ConstantUtils.REFUSE.equals(expenseEntity.getExpenseState());
    }

    @Override
    public void allDeptExpense( Long userId, ExpenseEntity expenseEntity) {
        ExpenseEntity expenseEntity1 = expenseMapper.selectByExpenseId(expenseEntity);
        String s = String.valueOf(expenseEntity1.getId());
        String deptRole = deptUserMapper.selectDeptByUserId(expenseEntity1.getExpenseUserId()).get(0).getDeptRole();
        //审核员
        if (ConstantUtils.ADMINISTRATOR.equals(deptRole) ||  ConstantUtils.ASSESSOR.equals(deptRole)) {
            expenseMap(expenseEntity, map);
            //拾取任务
            taskService.claim(expenseEntity.getExpenseTask(), String.valueOf(userId));
            taskService.complete(expenseEntity.getExpenseTask(), map);
            if (ConstantUtils.REJECT.equals(expenseEntity.getExpenseState())){
                Task task1 = updateExpense(s);
                expenseEntity.setExpenseTask(task1.getId());
            }
            expenseMapper.updateExpense(expenseEntity);
            map.clear();
        }
    }

    /**
     * 给财务部门流程变量赋值
     * @param expenseEntity 审批实体
     * @param map 流程变量容器
     */
    private void expenseMap(ExpenseEntity expenseEntity, HashMap<String, Object> map) {
        ChaimEntity chaimEntity = new ChaimEntity();
        if (equalsReject(expenseEntity)) {
            map.put(ConstantUtils.FINANCE_DEPT_NODE, ConstantUtils.REJECT);
            expenseEntity.setExpenseType(ConstantUtils.APPLY);
            chaimEntity.setChaimStatus(Integer.valueOf(ConstantUtils.REJECT));
            chaimEntity.setChaimCode(expenseEntity.getExpenseId());
            chaimMapper.updateChaimStatus(chaimEntity);
            expenseEntity.setExpenseState(ConstantUtils.REJECT);
        }
        if (equalsRefuse(expenseEntity)) {
            map.put(ConstantUtils.FINANCE_DEPT_NODE, ConstantUtils.PASS);
            expenseEntity.setExpenseType(ConstantUtils.END);
            expenseEntity.setDeleteMark(ConstantUtils.DELETE_MARK);
            chaimEntity.setChaimStatus(Integer.valueOf(ConstantUtils.REFUSE));
            chaimEntity.setChaimCode(expenseEntity.getExpenseId());
            chaimMapper.updateChaimStatus(chaimEntity);
            expenseEntity.setExpenseState(ConstantUtils.REFUSE);
        }
        if (equalsPass(expenseEntity)) {
            map.put(ConstantUtils.FINANCE_DEPT_NODE, ConstantUtils.PASS);
            expenseEntity.setExpenseType(ConstantUtils.SUCCESS);
            expenseEntity.setDeleteMark(ConstantUtils.DELETE_MARK);
            chaimEntity.setChaimStatus(Integer.valueOf(ConstantUtils.PASS));
            chaimEntity.setChaimCode(expenseEntity.getExpenseId());
            chaimMapper.updateChaimStatus(chaimEntity);
            expenseEntity.setExpenseState(ConstantUtils.PASS);
        }
    }

    @Override
    public Task updateExpense(String bizKey) {
        return taskService.createTaskQuery()
                .processDefinitionKey(ACTIVITI_KEY)
                .processInstanceBusinessKey(bizKey)
                .singleResult();
    }

//    @Override
//    public List<ActivitiVO> historyActInstanceList(ExpenseEntity expenseEntity) {
//        ExpenseEntity expenseEntity1 = expenseMapper.selectByExpenseId(expenseEntity);
//        if (Objects.isNull(expenseEntity1)){
//            throw new ServiceException(ApplicationResponseCode.ACTIVITI_END);
//        }
//        String s = String.valueOf(expenseEntity1.getId());
//        //获取流程实例
//        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
//                .processInstanceBusinessKey(s)
//                .singleResult();
//        //创建查询对象，用户查询历史任务
//        HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
//        //根据流程实例查询actinst
//        historicActivityInstanceQuery.processInstanceId(historicProcessInstance.getId());
//        //根据开始时间进行升序排序
//        historicActivityInstanceQuery.orderByHistoricActivityInstanceStartTime().asc();
//        List<HistoricActivityInstance> list = historicActivityInstanceQuery.list();
//        List<ActivitiVO> activitiVOList = new ArrayList<>();
//        for (HistoricActivityInstance historicActivityInstance:list){
//            ActivitiVO activitiVO = new ActivitiVO();
//            activitiVO.setProcessInstanceId(historicActivityInstance.getProcessInstanceId());
//            activitiVO.setActivityName(historicActivityInstance.getActivityName());
//            activitiVO.setActivityType(historicActivityInstance.getActivityType());
//            activitiVO.setTaskId(historicActivityInstance.getTaskId());
//            activitiVO.setAssignee(historicActivityInstance.getAssignee());
//            activitiVO.setStartTime(historicActivityInstance.getStartTime());
//            activitiVO.setEndTime(historicActivityInstance.getEndTime());
//            activitiVOList.add(activitiVO);
//            //将网关排除
//            if (ConstantUtils.GATE_WAY.equals(activitiVO.getActivityType())) {
//                activitiVOList.remove(activitiVO);
//            }
//        }
//        return activitiVOList;
//    }

    @Override
    public void expenseTask(Long userId, ExpenseEntity expenseEntity) {
        //登录人是本部门的人，执行本部门审批
        ExpenseEntity expenseEntity1 = expenseMapper.selectByTask(expenseEntity.getExpenseTask());
        if (ConstantUtils.DEPT_APPROVAL.equals(expenseEntity1.getExpenseType())){
            expenseEntity.setExpenseUserId(userId);
            expenseEntity.setApplyUserId(expenseEntity1.getApplyUserId());
            deptExpense(expenseEntity);
        }
        if (ConstantUtils.PARENT_APPROVAL.equals(expenseEntity1.getExpenseType())){
            expenseEntity.setExpenseUserId(userId);
            expenseEntity.setApplyUserId(expenseEntity1.getApplyUserId());
            parentExpense(userId,expenseEntity);
        }
        if (ConstantUtils.FINANCE_APPROVAL.equals(expenseEntity1.getExpenseType())){
            expenseEntity.setExpenseUserId(userId);
            expenseEntity.setApplyUserId(expenseEntity1.getApplyUserId());
            allDeptExpense(userId,expenseEntity);
        }

    }

    @Override
    public ExpenseEntity selectByExpenseId(ExpenseEntity expenseEntity) {
        return expenseMapper.selectByExpenseId(expenseEntity);
    }

    @Override
    public List<ExpenseEntity> selectByExpenseCode(ExpenseEntity expenseEntity) {
        return null;
    }

    @Override
    public List<ExpenseEntity> selectByExpense(Long userId) {
        List<Task> result = taskService.createTaskQuery()
                .processDefinitionKey(ACTIVITI_KEY)
                .taskCandidateUser(String.valueOf(userId)).list();
        if(CollectionUtils.isEmpty(result)){
            throw new ServiceException(ApplicationResponseCode.TASK_NOT_FOUND);
        }
        List<ExpenseEntity> taskInfo = new ArrayList<>();
        for(Task task : result){
            ExpenseEntity expenseEntity1 = expenseMapper.selectByTask(task.getId());
            taskInfo.add(expenseEntity1);
        }
        return taskInfo;
    }

    @Override
    public List<ExpenseEntity> completeTask(Long userId) {
        //查询该用户的已审任务
        List<HistoricTaskInstance> assigneeTasks = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(String.valueOf(userId)).finished().list();
        List<HistoricTaskInstance> userTasks = historyService.createHistoricTaskInstanceQuery()
                .taskCandidateUser(String.valueOf(userId)).finished().list();
        if(CollectionUtils.isEmpty(assigneeTasks)&&CollectionUtils.isEmpty(userTasks)){
            throw new ServiceException(ApplicationResponseCode.COMPLETE_NOT_TASK);
        }
        userTasks.addAll(assigneeTasks);
        //去重
        HashSet set = new HashSet(userTasks);
        userTasks.clear();
        userTasks.addAll(set);
        //审批单集合
        List<ExpenseEntity> leaveApprovalVOList = new ArrayList<>();
        //将任务赋值到审批单
//        if(!CollectionUtils.isEmpty(userTasks)){
//            for(int j=0;j<userTasks.size();j++){
//                TaskVO taskDTO = new TaskVO();
//                taskDTO.setTaskId(userTasks.get(j).getId());
//                taskDTO.setAssignee(userTasks.get(j).getAssignee());
//                taskDTO.setProcessinstanceId(userTasks.get(j).getProcessInstanceId());
//                taskDTO.setTaskName(userTasks.get(j).getName());
//                //历史实例过程查询
//                HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery()
//                        .processInstanceId(taskDTO.getProcessinstanceId()).singleResult();
//                taskDTO.setBusinesskey(hpi.getBusinessKey());
//                if(!StringUtils.isEmpty(taskDTO.getBusinesskey())){
//                    ExpenseEntity expenseEntity = expenseMapper.selectById(Long.valueOf(taskDTO.getBusinesskey()));
//                    leaveApprovalVOList.add(expenseEntity);
//                }
//            }
//        }
        //去重
        HashSet hashSet = new HashSet(leaveApprovalVOList);
        leaveApprovalVOList.clear();
        leaveApprovalVOList.addAll(hashSet);
        return leaveApprovalVOList;
    }

    @Override
    public List<ExpenseEntity> selectByApplyUserId(ExpenseEntity expenseEntity) {
        return expenseMapper.selectByApplyUserId(expenseEntity);
    }

}
